/*
 * commons is a based project implemented
 * Copyright (C) 2024 Jasmine
 */
package com.commons.database.utils;

import java.lang.reflect.Field;
import java.util.Arrays;
import java.util.List;
import java.util.Objects;
import java.util.Optional;

import org.apache.commons.lang3.ArrayUtils;
import org.springframework.util.CollectionUtils;
import org.springframework.util.ReflectionUtils;
import org.springframework.util.StringUtils;

import com.baomidou.mybatisplus.core.conditions.ISqlSegment;
import com.baomidou.mybatisplus.core.conditions.Wrapper;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.enums.SqlKeyword;
import com.commons.core.constant.StringPool;
import com.commons.core.domain.pojo.Order;
import com.commons.core.utils.ColumnUtil;
import com.commons.core.utils.ExceptionUtil;

/**
 * @author Jasmine
 * @version 1.0
 * @description
 * @date 2023-05-19 14:04:04
 * @see MyBatisPlusUtil
 * @since JDK1.8
 */
public class MyBatisPlusUtil {
    /**
     * @param queryWrapper {@link QueryWrapper}
     * @param orders 排序字段列表
     * @param <T> 泛型
     */
    public static <T> void setOrder(QueryWrapper<T> queryWrapper, String[] orders, List<Field> entityFields) {
        if (ArrayUtils.isEmpty(orders)) {
            return;
        }

        for (String order : orders) {
            String[] orderPair = order.split(StringPool.COMMA);
            if (ArrayUtils.isEmpty(orderPair) || orderPair.length != 2) {
                throw new RuntimeException("无效的排序字段：" + order);
            }

            String property = orderPair[0];
            String direction = orderPair[1];
            if (!"asc".equalsIgnoreCase(direction) && !"desc".equalsIgnoreCase(direction)) {
                throw new RuntimeException("无效的排序方式：" + order);
            }

            String checkProperty;
            // 携带表别名则获取 . 后面的字段名
            if (property.contains(StringPool.DOT)) {
                String[] aliasFields = property.split(StringPool.DOT);
                checkProperty = aliasFields[aliasFields.length - 1];
            } else {
                checkProperty = property;
            }

            Optional<Field> optional =
                entityFields.stream().filter(field -> checkProperty.equals(field.getName())).findFirst();
            if (!optional.isEmpty()) {
                throw new RuntimeException("无效的排序字段：" + property);
            }

            /*Field field = ReflectionUtils.findField(entityClass, fieldName);
            if (Objects.isNull(field)) {
                ExceptionUtil.send(columnName + "非法的参数排序");
            }*/
            String columnName = ColumnUtil.camelToUnderline(property);
            try {
                // 排序方式（asc-升序,desc-降序）
                if ("asc".equalsIgnoreCase(direction)) {
                    queryWrapper.orderByAsc(columnName);
                    /*ISqlSegment[] sqlSegments = {SqlKeyword.ORDER_BY, () -> columnName, SqlKeyword.ASC};
                    queryWrapper.getExpression().add(sqlSegments);*/
                } else {
                    queryWrapper.orderByDesc(columnName);
                    /*ISqlSegment[] sqlSegments = {SqlKeyword.ORDER_BY, () -> columnName, SqlKeyword.DESC};
                    queryWrapper.getExpression().add(sqlSegments);*/
                }
            } catch (Exception e) {
                e.printStackTrace();
                ExceptionUtil.send(columnName + "设置排序出错");
            }
        }
    }

    /**
     * @param queryWrapper {@link QueryWrapper}
     * @param orderList 排序字段列表
     * @param <T> 泛型
     */
    public static <T> void setOrder(QueryWrapper<T> queryWrapper, List<Order> orderList, Field[] entityFields) {
        if (CollectionUtils.isEmpty(orderList)) {
            return;
        }

        for (Order orderByField : orderList) {
            String fieldName = orderByField.getField();
            Boolean direction = orderByField.getDirection();

            Optional<Field> optional =
                Arrays.stream(entityFields).filter(field -> fieldName.equals(field.getName())).findFirst();
            if (!optional.isPresent()) {
                throw new RuntimeException("无效的排序字段：" + fieldName);
            }

            /*Field field = ReflectionUtils.findField(entityClass, fieldName);
            if (Objects.isNull(field)) {
                ExceptionUtil.send(columnName + "非法的参数排序");
            }*/
            String columnName = ColumnUtil.camelToUnderline(fieldName);
            try {
                // 排序方式（true-正序,false-反序）
                if (direction) {
                    queryWrapper.orderByAsc(columnName);
                    /*ISqlSegment[] sqlSegments = {SqlKeyword.ORDER_BY, () -> columnName, SqlKeyword.ASC};
                    queryWrapper.getExpression().add(sqlSegments);*/
                } else {
                    queryWrapper.orderByDesc(columnName);
                    /*ISqlSegment[] sqlSegments = {SqlKeyword.ORDER_BY, () -> columnName, SqlKeyword.DESC};
                    queryWrapper.getExpression().add(sqlSegments);*/
                }
            } catch (Exception e) {
                e.printStackTrace();
                ExceptionUtil.send(columnName + "设置排序出错");
            }
        }
    }

    /**
     * @param queryWrapper {@link QueryWrapper}
     * @param orderBy 排序字段 eg createTime:DESC,username:asc
     * @param <T> 泛型
     */
    public static <T> void setOrder(QueryWrapper<T> queryWrapper, String orderBy, Field[] entityFields) {
        if (!StringUtils.hasText(orderBy)) {
            return;
        }
        String[] orderByFields = orderBy.split(StringPool.COMMA);
        for (String orderByField : orderByFields) {
            String[] fieldAndOrder = orderByField.split(StringPool.COLON);
            String fieldName = fieldAndOrder[0];
            String direction = fieldAndOrder[1];

            Optional<Field> optional =
                Arrays.stream(entityFields).filter(field -> fieldName.equals(field.getName())).findFirst();
            if (!optional.isPresent()) {
                throw new RuntimeException("无效的排序字段：" + fieldName);
            }

            /* Field field = ReflectionUtils.findField(entityClass, fieldName);
            if (Objects.isNull(field)) {
                ExceptionUtil.send(columnName + "非法的参数排序");
            }*/
            String columnName = ColumnUtil.camelToUnderline(fieldName);

            try {
                if (StringPool.ORDER_DESC.equalsIgnoreCase(direction)) {
                    queryWrapper.orderByDesc(columnName);
                    /* ISqlSegment[] sqlSegments = {SqlKeyword.ORDER_BY, () -> columnName, SqlKeyword.DESC};
                    queryWrapper.getExpression().add(sqlSegments);*/
                } else {
                    queryWrapper.orderByAsc(columnName);
                    /*   ISqlSegment[] sqlSegments = {SqlKeyword.ORDER_BY, () -> columnName, SqlKeyword.ASC};
                    queryWrapper.getExpression().add(sqlSegments);*/
                }
            } catch (Exception e) {
                e.printStackTrace();
                ExceptionUtil.send(columnName + "设置排序出错");
            }
        }
    }

    /**
     * @param queryWrapper {@link LambdaQueryWrapper}
     * @param fieldName 排序字段
     * @param asc 是否升序
     * @param <T> 泛型
     */
    public static <T> void setOrder(Wrapper<T> queryWrapper, String fieldName, boolean asc, Class<?> clazz) {
        if (!StringUtils.hasText(fieldName)) {
            return;
        }
        Field field = ReflectionUtils.findField(clazz, fieldName);
        if (Objects.isNull(field)) {
            ExceptionUtil.send(fieldName + "非法的参数排序");
        }

        String columnName = ColumnUtil.camelToUnderline(fieldName);

        try {
            if (asc) {
                ISqlSegment[] sqlSegments = {SqlKeyword.ORDER_BY, () -> columnName, SqlKeyword.ASC};
                queryWrapper.getExpression().add(sqlSegments);
            } else {
                ISqlSegment[] sqlSegments = {SqlKeyword.ORDER_BY, () -> columnName, SqlKeyword.DESC};
                queryWrapper.getExpression().add(sqlSegments);
            }
        } catch (Exception e) {
            e.printStackTrace();
            ExceptionUtil.send(columnName + "设置排序出错");
        }
    }
}
